// Author: wsfuyibing <682805@qq.com>
// Date: 2025-06-21

package state

import (
	"context"
	"gitee.com/go-libs/db-xorm/db"
	"gitee.com/go-libs/result"
	"gitee.com/go-libs/validator-iris/validator"
	"gitee.com/go-wares/framework-iris/framework/src/logics"
	"github.com/kataras/iris/v12"
	"server/app/errs"
	"server/app/http/models"
	"server/app/http/services"
	"server/app/lib"
)

// Logic
// 更新场次状态.
type Logic struct {
	arcade *models.Arcades
	admin  *models.ArcadeAdmins

	affects int64
	ignored bool
	session *models.TicketSession
	ticket  *models.Ticket

	request  *Request
	response *Response
}

// New
// 创建逻辑实例.
func New() logics.Logical {
	return &Logic{
		request:  &Request{},
		response: &Response{},
	}
}

// Before
// 前置校验.
func (o *Logic) Before(_ context.Context, i iris.Context) (err error) {
	if err = validator.Json(i, o.request); err == nil {
		o.arcade, _ = lib.Arcade.GetMaster().GetArcade(i)
	}
	return
}

// Run
// 执行逻辑.
func (o *Logic) Run(ctx context.Context, _ iris.Context) result.Result {
	var (
		err error
		res = result.New()
	)

	// 1. 事务处理.
	if err = db.Transaction(ctx,
		o.RunCheck,
		o.RunUpdate,
		o.RunUpdateRecord,
	); err != nil {
		return res.WithError(err)
	}

	// 2. 加载完成.
	return res.With(o.response)
}

// RunCheck
// 检查场次.
func (o *Logic) RunCheck(ctx context.Context, sess *db.Session) error {
	var (
		err error
		has bool
	)

	// 1. 读取场次.
	if o.session, has, err = services.NewTicketSessionService(sess).Dao.GetById(ctx, o.request.Id); err != nil {
		return errs.ErrDatabaseQuery
	} else if !has || o.session.Deleted.IsYes() || o.session.ArcadeId != o.arcade.Id {
		return errs.ErrTicketSessionNotFound
	}

	// 2. 读取渔票.
	if o.ticket, has, err = services.NewTicketService(sess).Dao.GetById(ctx, o.session.TicketId); err != nil {
		return errs.ErrDatabaseQuery
	} else if !has || o.ticket.Deleted.IsYes() || o.ticket.ArcadeId != o.arcade.Id {
		return errs.ErrTicketNotFound
	}

	// 3. 忽略状态
	o.ignored = o.session.State == o.request.State
	return nil
}

// RunUpdate
// 更新状态.
func (o *Logic) RunUpdate(ctx context.Context, sess *db.Session) (err error) {
	// 1. 忽略任务.
	if o.ignored {
		return
	}

	// 2. 更新状态.
	if o.affects, err = services.NewTicketSessionService(sess).Dao.UpdateFieldsById(ctx, map[string]any{
		"state": o.request.State,
	}, o.session.Id); err != nil {
		err = errs.ErrDatabaseQuery
		return
	}

	// 3. 更新成功.
	o.session.State = o.request.State
	return
}

// RunUpdateRecord
// 同步记录.
func (o *Logic) RunUpdateRecord(ctx context.Context, sess *db.Session) (err error) {
	// 1. 忽略处理.
	//    a. 前一步操作成功
	//    b. 渔票为同时开钓
	//    c. 操作为同时开竿
	if o.ignored || o.affects == 0 || !o.request.State.IsStarted() || !o.ticket.Time.IsStrict() {
		return
	}

	// 2. 批量更新.
	if _, err = services.NewTicketRecordService(sess).Dao.UpdateFieldsByMap(ctx,
		map[string]any{
			"time_start": o.session.TimeStart,
			"time_end":   o.session.TimeEnd,
		}, map[string]any{
			"session_id": o.session.Id,
		},
	); err != nil {
		err = errs.ErrDatabaseQuery
	}
	return
}
